home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / MM2_DEV / S / MYUTIL / MULTITAS.M < prev    next >
Encoding:
Text File  |  1990-11-16  |  4.7 KB  |  3 lines

  1. ⓪ MODULE MultiTask; (*$E MOS *)⓪ (*$R-*)⓪ ⓪ (*⓪ >>> Das Ganze geht aus einem Grunde nicht:⓪"Wenn z.b. der Timer-IR auftritt, während gerade der VBL-IR läuft,⓪"würde durch den IOTRANSFER der VBL unterbrochen werden. Das darf⓪"aber nicht sein, stattdessen müßte erst der VBL beendet und erst⓪"dann der timer-IR zugelassen werden. Dies wird bei Multitask-Systemen⓪"i.a. so gelöst, daß der scheduler-IR eine niedrigere Priorität als⓪"alle System-IRs bekommt. Oder eben so, daß durch Semaphore o.ä.⓪"dafür gesorgt wird, daß der Timer-IR bis zum Ende der System-IRs⓪"wartet.⓪"Hier könnte man es entweder so lösen, daß als timer-IR der VBL-⓪"Hardware-Vektor verwendet wird oder daß man sich in alle Sytem-IRs⓪"hängt und semaphore setzt.⓪ *)⓪ ⓪ (*⓪!* Demo für Modula-Coroutinen, die per Interrupt umgeschaltet werden⓪!* ("Time Slice").⓪!*⓪!* Das Demo-Programm geht nur von zwei Coroutinen aus, die abwechselnd⓪!* aktiviert werden sollen. Ein richtiger Scheduler (Prozeß-Verwalter/⓪!* Umschalter) würde stattdessen eine erweiterbare Liste für beliebig⓪!* viele Coroutinen verwalten und sie alle abwechselnd aktivieren.⓪!*⓪!* Die Coroutinen werden folgendermaßen abwechselnd aktiviert: Zuerst⓪!* einmal läuft das Hauptprogramm (Prozedur 'mainProgram'). Jede zwanzigstel⓪!* Sekunde wird die erste Coroutine für eine fünfzigstel Sekunde aktiviert.⓪!* Nach Ablauf einer Sekunde wird dann stattdessen die zweite Coroutine⓪!* alle 1/20s für jeweils 1/50s aktiviert. Nach einer weiteren Sekunde⓪!* wieder die erste, usw.⓪!*⓪!* Das bedeutet:⓪!⓪!* Die scheduler-Funktion (s.u.) benutzt den 200Hz-Interrupt-Vektor,⓪!* sie wird also 200 mal pro Sekunde aufgerufen. Die Funktion installiert⓪!* sich auf den Vektor mit IOTRANSFER. Jedesmal, wenn der Vektor ange-⓪!* sprungen wird, wird die unterbrochene Coroutine (bzw. das unterbrochene⓪!* Programm) im ersten Parameter zu IOTRANSFER ('suspendedCor') gespeichert.⓪!* Der Scheduler zählt nun einen Zähler herunter. Ist er nicht abgelaufen,⓪!* wird gleich wieder mit IOTRANSFER zur unterbrochenen Routine zurückgekehrt.⓪!* Andernfalls wird eine der zwei wartenden Coroutinen⓪!*⓪!Ist der Zähler abgelaufen, wird jeweils⓪!* eine der wartenden Coroutinen aktiviert. Der Zähler zählt 400 Werte,⓪!* die Coroutinen werden demnach alle 2 Sekunden umgeschaltet.⓪!*⓪!* Zur Sichtbarmachung der Aktionen der beiden Coroutinen⓪!* sie beide an verschiedenen Stellen auf dem Bildschirm herum. Dies⓪!* geschieht durch Direktzugriff auf den Bildschirmspeicher, weil⓪!* ein Aufruf von Ein-/Ausgabe-Funktionen (GEM, GEMDOS, BIOS) in⓪!* Interrupts so einfach nicht erlaubt ist.⓪!!Info-Line raus!⓪!*)⓪ ⓪ FROM SYSTEM IMPORT ADDRESS, ADR, IOTRANSFER, TRANSFER, NEWPROCESS, IOCALL;⓪ FROM SYSTEM IMPORT ASSEMBLER;⓪ (*⓪ FROM SysVars IMPORT etv_timer;⓪ *)⓪ FROM XBIOS IMPORT ScreenLogicalBase;⓪ FROM Terminal IMPORT WriteString, WriteLn, Write;⓪ ⓪ CONST etv_timer =$114;⓪ ⓪ VAR  mainCor: ADDRESS;                     (* Hauptprogramm *)⓪%schedCor: ADDRESS;                    (* Scheduler-Coroutine *)⓪%cor1, cor2: ADDRESS;                  (* die Hintergrund-Coroutinen *)⓪ ⓪%screen: POINTER TO ARRAY [0..399] OF ARRAY [0..39] OF BITSET;⓪%seconds: CARDINAL;⓪%terminate: BOOLEAN;⓪ ⓪ PROCEDURE lauflicht (offset: CARDINAL; VAR pos: CARDINAL);⓪"VAR b: BITSET;⓪"BEGIN⓪$b:= {};⓪$INCL (b, pos);⓪$IF pos=0 THEN pos:= 15; ELSE DEC (pos) END;⓪$screen^[1,offset]:= b;⓪$screen^[2,offset]:= b;⓪$screen^[3,offset]:= b;⓪$screen^[4,offset]:= b;⓪"END lauflicht;⓪ ⓪ PROCEDURE funktion1;⓪"VAR pos: CARDINAL;⓪"BEGIN⓪$pos:= 0;⓪$LOOP⓪&lauflicht (4, pos);⓪$END⓪"END funktion1;⓪ ⓪ PROCEDURE funktion2;⓪"VAR pos: CARDINAL;⓪"BEGIN⓪$pos:= 0;⓪$LOOP⓪&lauflicht (8, pos);⓪$END⓪"END funktion2;⓪ ⓪ PROCEDURE mainProgram;⓪"(*⓪#* Diese Prozedur läuft als Hauptprogramm, also nicht im Interrupt.⓪#*)⓪"VAR last: CARDINAL; l: LONGCARD;⓪"BEGIN⓪$seconds:= 0;              (* Sekundenzähler, wird vom Scheduler erhöht *)⓪$last:= seconds;⓪$REPEAT⓪&(* Gibt jede Sekunde ein Zeichen aus: *)⓪&IF last # seconds THEN⓪(last:= seconds;⓪(Write ('#');⓪&END⓪$UNTIL FALSE (*seconds = 6;  (* Ende nach 6 Sekunden *)*)⓪"END mainProgram;⓪ ə
  2. (* $FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$00000D26$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DCÇ$00000027T.......T.......T.......T.......T.......T.......T.......T.......T.......T.......$00000027$000000EA$FFEE50DC$00000EA4$00000B77$00001031$0000105B$FFEE50DC$FFEE50DC$000002F0$00000091$0000006B$000002F0$000002E1$00000031$000002F0êÇé*)
  3.